﻿using System;
using System.Threading;
using Stateless;

/// <summary>
/// 状态机
/// </summary>
namespace StateMachineTest
{
    /// <summary>
    /// 状态机分层
    /// </summary>
    class Program
    {
        /// <summary>
        /// 状态机对象
        /// </summary>
        static StateMachine<TelState, TelTrigger> _stateMachine;

        /// <summary>
        /// 是否重新接入
        /// </summary>
        static bool _isReConnect = false;

        static void Main(string[] args)
        {
            _stateMachine = new StateMachine<TelState, TelTrigger>(TelState.NoRing);


            _stateMachine.Configure(TelState.NoRing)
                .Permit(TelTrigger.Ring, TelState.Ringing);

            _stateMachine.Configure(TelState.Ringing)
                .OnEntry(EntryRinging)
                .OnExit(ExitRinging)
                .Permit(TelTrigger.CallConnected, TelState.Connected)
                .Permit(TelTrigger.LeftMessage, TelState.OffHook);

            _stateMachine.Configure(TelState.Connected)
                .OnEntry(EntryConnected)
                .OnExit(ExitConnected)
                .Permit(TelTrigger.PlacedOnHold, TelState.OnHold)
                .Permit(TelTrigger.LeftMessage, TelState.OffHook);

            _stateMachine.Configure(TelState.OnHold)
                // 标记为Connected的子状态
                .SubstateOf(TelState.Connected)
                .OnEntry(EntryOnHold)
                .OnExit(ExitOnHold)
                .Permit(TelTrigger.CallConnected, TelState.Connected)
                .Permit(TelTrigger.LeftMessage, TelState.OffHook);

            _stateMachine.Configure(TelState.OffHook)
                .OnEntry(EntryOffHook);

            // 触发状态机
            _stateMachine.Fire(TelTrigger.Ring);
            Console.ReadKey();
        }

        static void EntryRinging()
        {
            Console.WriteLine("EntryRinging");
            Thread.Sleep(3000);
            _stateMachine.Fire(TelTrigger.CallConnected);
        }

        static void ExitRinging()
        {
            Console.WriteLine("ExitRinging");
        }

        static void EntryConnected()
        {
            Console.WriteLine("EntryConnected");
            Thread.Sleep(3000);
            // 模拟重新挂起后重新连接
            if (_isReConnect)
            {
                _isReConnect = !_isReConnect;
                _stateMachine.Fire(TelTrigger.LeftMessage);
            }
            else
            {
                _isReConnect = !_isReConnect;
                _stateMachine.Fire(TelTrigger.PlacedOnHold);
            }  
        }

        static void ExitConnected()
        {
            Console.WriteLine("ExitConnected");
        }

        static void EntryOnHold()
        {
            Console.WriteLine("EntryOnHold");
            Thread.Sleep(3000);
            _stateMachine.Fire(TelTrigger.CallConnected);
        }

        static void ExitOnHold()
        {
            Console.WriteLine("ExitOnHold");
        }

        static void EntryOffHook()
        {
            Console.WriteLine("EntryOffHook");
        }
    }


    /// <summary>
    /// 电话拨号-状态
    /// </summary>
    enum TelState
    {
        /// <summary>
        /// 未响铃
        /// </summary>
        NoRing,
        /// <summary>
        /// 响铃
        /// </summary>
        Ringing,
        /// <summary>
        /// 已连接
        /// </summary>
        Connected,
        /// <summary>
        /// 挂起(Connected的子状态)
        /// </summary>
        OnHold,
        /// <summary>
        /// 挂断
        /// </summary>
        OffHook,
    }


    /// <summary>
    /// 电话拨号-触发器
    /// </summary>
    enum TelTrigger
    {
        /// <summary>
        /// 响铃
        /// </summary>
        Ring,
        /// <summary>
        /// 连接
        /// </summary>
        CallConnected,
        /// <summary>
        /// 请等待
        /// </summary>
        PlacedOnHold,
        /// <summary>
        /// 离开对话
        /// </summary>
        LeftMessage,
    }
}
